package com.singleton.other;

/**
 * Created by Administrator on 2017/6/6.
 * 懒汉单例模式
 * 懒汉单例模式在第一次调用getInstance的时候实例化，
 * 类加载的时候并不自行实例化，需要的时候在加载实例，
 * 为了避免多个线程同时调用，加了线程锁synchronized
 *
 * 懒汉单例模式加了线程锁sycchronized,处理了多个线程
 * 同时访问的问题。但是，上述代码虽然解决了线程安全问题
 * 但是在高并发访问环境中，每次都需要线程锁定判断，降低系统
 * 性能，事实上无需对getInstance整块锁定，只需要锁定instance = new lazyInstance();
 *
 *
 */
public class lazySingleton {

    private volatile static lazySingleton instance = null ;

    private lazySingleton(){}

    //原始
//    synchronized  public static lazySingleton getInstance(){
//        if(instance == null){
//            instance = new lazySingleton();
//        }
//        return instance;
//    }

    //改进1
    //改进的代码还是回存在单例不唯一的情况
    //当线程A和线程B在某一时刻同时调用，此时的instance == null
    //条件都满足，由于线程锁的机制，线程A进入了synchronized锁定的
    //代码中执行创建代码，B在排队等待状态，必须等待A执行完之后才能执行
    //当A执行完代码之后，B不知道A已经创建，将会继续创建新的实例，
    //因此需要进一步的改进
//    public static lazySingleton getInstance(){
//        if(instance == null){
//            synchronized (lazySingleton.class){
//                instance = new lazySingleton();
//            }
//        }
//        return instance;
//    }

    //改进2
    //双重锁定实现懒汉模式
    //需要注意的是双重锁定模式需要在静态成员变量instance前加上volatile
    public static lazySingleton getInstance(){
        if(instance == null){
            synchronized (lazySingleton.class){
                if(instance == null){
                    instance = new lazySingleton();
                }
            }
        }
        return instance;
    }
}

//懒汉模式和饿汉模式的比较
//饿汉单例模式在类被加载的时候就实例化，他的优点在于无需考虑多线程访问的问题
//可以确保实例的唯一性，从调用速度和反应时间来讲，由于单例对象在一开始就被创建，
//因此要由于懒汉式单例。但是无论系统在运行时是否需要使用单例对象，由于在类加载是
//该对象就需要创建，因此从资源利用的角度来讲的话，饿汉单例模式不如懒汉单例模式
//而且在类加载的时候就需要创建饿汉单例模式对象，加载时间可能会比较长

//懒汉单例模式在第一次使用的时候创建。无需一直占用系统资源，实现了延迟加载，但是
//必须处理多线程同时访问的问题，特别的是单例作为资源控制器，在实例化的时候必然涉及
//资源初始化，而资源初始化很可能耗费大量的时间。这意味着出现多线程同时首次引用此类
//的几率变得较大，需要通过双重检查锁定等机制进行控制，这将导致系统性能收到一定的影响
